home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / c / cxref-1.001 / cxref-1~ / cxref / html.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-24  |  29.7 KB  |  1,141 lines

  1. /***************************************
  2.   $Header: /home/amb/cxref/RCS/html.c 1.8 1996/02/24 14:53:19 amb Exp $
  3.  
  4.   C Cross Referencing & Documentation tool. Version 1.0
  5.  
  6.   Writes the HTML output.
  7.   ******************/ /******************
  8.   Written by Andrew M. Bishop
  9.  
  10.   This file Copyright 1995,96 Andrew M. Bishop
  11.   It may be distributed under the GNU Public License, version 2, or
  12.   any higher version.  See section COPYING of the GNU Public license
  13.   for conditions under which this file may be redistributed.
  14.   ***************************************/
  15.  
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <sys/stat.h>
  20. #include <unistd.h>
  21.  
  22. #ifndef min
  23. #define min(x,y) ( (x) < (y) ? (x) : (y) )
  24. #endif
  25.  
  26. #include "memory.h"
  27. #include "datatype.h"
  28. #include "cxref.h"
  29.  
  30. /*+ The name of the output tex file that includes each of the others. +*/
  31. #define HTML_FILE        ".html"
  32. #define HTML_FILE_BACKUP ".html~"
  33.  
  34. /*+ The name of the output tex file that contains the appendix. +*/
  35. #define HTML_APDX_FILE        ".apdx.html"
  36.  
  37. /*+ The name of the directory for the output. +*/
  38. extern char* option_odir;
  39.  
  40. /*+ The base name of the file for the output. +*/
  41. extern char* option_name;
  42.  
  43. /*+ The diretories to go back to get to the base output directory. +*/
  44. static char* goback=NULL;
  45.  
  46. static void WriteHTMLFilePart(File file);
  47. static void WriteHTMLInclude(Include inc);
  48. static void WriteHTMLSubInclude(Include inc,int depth);
  49. static void WriteHTMLDefine(Define def);
  50. static void WriteHTMLTypedef(Typedef type);
  51. static void WriteHTMLStructUnion(StructUnion su, int depth);
  52. static void WriteHTMLVariable(Variable var);
  53. static void WriteHTMLFunction(Function func);
  54.  
  55. static void WriteHTMLDocument(char* name);
  56. static void WriteHTMLPreamble(FILE* f,char* title);
  57. static void WriteHTMLPostamble(FILE* f);
  58. static void AddHTMLAppendix(void);
  59.  
  60. static char* html(char* c);
  61.  
  62. /*+ The output file for the HTML. +*/
  63. static FILE* of;
  64.  
  65. /*++++++++++++++++++++++++++++++++++++++
  66.   Write an html file for a complete File structure and all components.
  67.  
  68.   File file The File structure to output.
  69.   ++++++++++++++++++++++++++++++++++++++*/
  70.  
  71. void WriteHTMLFile(File file)
  72. {
  73.  char* ofile;
  74.  int i;
  75.  
  76.  /* Write the including file. */
  77.  
  78.  WriteHTMLDocument(file->name);
  79.  
  80.  /* Open the file */
  81.  
  82.  ofile=ConcatStrings(4,option_odir,"/",file->name,HTML_FILE);
  83.  
  84.  of=fopen(ofile,"w");
  85.  
  86.  if(!of)
  87.    {fprintf(stderr,"cxref: Failed to open the HTML output file '%s'\n",ofile);exit(1);}
  88.  
  89.  for(goback="",i=strlen(file->name);i>0;i--)
  90.     if(file->name[i]=='/')
  91.        goback=ConcatStrings(2,goback,"../");
  92.  
  93.  /* Write out a header. */
  94.  
  95.  WriteHTMLPreamble(of,ConcatStrings(5,"Cross reference for ",file->name," of ",option_name,"."));
  96.  
  97.  /*+ The file structure is broken into its components and they are each written out. +*/
  98.  
  99.  WriteHTMLFilePart(file);
  100.  
  101.  if(file->includes)
  102.    {
  103.     Include inc =file->includes;
  104.     fprintf(of,"<hr>\n<h2>Included Files</h2>\n\n");
  105.     do{
  106.        WriteHTMLInclude(inc);
  107.       }
  108.     while((inc=inc->next));
  109.    }
  110.  
  111.  if(file->defines)
  112.    {
  113.     Define def =file->defines;
  114.     fprintf(of,"<hr>\n<h2>Preprocessor definitions</h2>\n\n");
  115.     do{
  116.        if(def!=file->defines)
  117.           fprintf(of,"<p>\n");
  118.        WriteHTMLDefine(def);
  119.       }
  120.     while((def=def->next));
  121.    }
  122.  
  123.  if(file->typedefs)
  124.    {
  125.     Typedef type=file->typedefs;
  126.     do{
  127.        WriteHTMLTypedef(type);
  128.       }
  129.     while((type=type->next));
  130.    }
  131.  
  132.  if(file->variables)
  133.    {
  134.     int any_to_mention=0;
  135.     Variable var=file->variables;
  136.  
  137.     do{
  138.        if(var->scope&(GLOBAL|LOCAL|EXTERNAL))
  139.           any_to_mention=1;
  140.       }
  141.     while((var=var->next));
  142.  
  143.     if(any_to_mention)
  144.       {
  145.        int first_ext=1,first_local=1;
  146.        Variable var=file->variables;
  147.        do{
  148.           if(var->scope&GLOBAL)
  149.              WriteHTMLVariable(var);
  150.          }
  151.        while((var=var->next));
  152.        var=file->variables;
  153.        do{
  154.           if(var->scope&EXTERNAL && !(var->scope&GLOBAL))
  155.             {
  156.              if(first_ext)
  157.                {fprintf(of,"<hr>\n<h2>External Variables</h2>\n\n"); first_ext=0;}
  158.              else
  159.                 fprintf(of,"<p>\n");
  160.              WriteHTMLVariable(var);
  161.             }
  162.          }
  163.        while((var=var->next));
  164.        var=file->variables;
  165.        do{
  166.           if(var->scope&LOCAL)
  167.             {
  168.              if(first_local)
  169.                {fprintf(of,"<hr>\n<h2>Local Variables</h2>\n\n"); first_local=0;}
  170.              else
  171.                 fprintf(of,"<p>\n");
  172.              WriteHTMLVariable(var);
  173.             }
  174.          }
  175.        while((var=var->next));
  176.       }
  177.    }
  178.  
  179.  if(file->functions)
  180.    {
  181.     Function func=file->functions;
  182.     do{
  183.        if(func->scope&GLOBAL)
  184.           WriteHTMLFunction(func);
  185.       }
  186.     while((func=func->next));
  187.     func=file->functions;
  188.     do{
  189.        if(func->scope&LOCAL)
  190.           WriteHTMLFunction(func);
  191.       }
  192.     while((func=func->next));
  193.    }
  194.  
  195.  WriteHTMLPostamble(of);
  196.  
  197.  fclose(of);
  198.  
  199. /* Clear the memory in html() */
  200.  
  201.  html(NULL); html(NULL); html(NULL); html(NULL);
  202. }
  203.  
  204.  
  205. /*++++++++++++++++++++++++++++++++++++++
  206.   Write a File structure out.
  207.  
  208.   File file The File to output.
  209.   ++++++++++++++++++++++++++++++++++++++*/
  210.  
  211. static void WriteHTMLFilePart(File file)
  212. {
  213.  int i;
  214.  
  215.  fprintf(of,"\n<a name=\"file\">\n<h1>File %s</h1>\n</a>\n",html(file->name));
  216.  
  217.  if(file->comment)
  218.    {
  219.     char *rcs1=strstr(file->comment,"$Header"),*rcs2=NULL;
  220.     if(rcs1)
  221.       {
  222.        rcs2=strstr(&rcs1[1],"$");
  223.        if(rcs2)
  224.          {
  225.           rcs2[0]=0;
  226.           fprintf(of,"<b>RCS %s</b>\n<p>\n",html(&rcs1[1]));
  227.           rcs2[0]='$';
  228.          }
  229.       }
  230.     if(rcs2)
  231.        fprintf(of,"%s\n<p>\n",html(&rcs2[2]));
  232.     else
  233.        fprintf(of,"%s\n<p>\n",html(file->comment));
  234.    }
  235.  
  236.  if(file->inc_in.n)
  237.    {
  238.     int i;
  239.  
  240.     fprintf(of,"<dl compact>\n<dt>Included in:\n<dd><menu>\n");
  241.     for(i=0;i<file->inc_in.n;i++)
  242.        fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#file\">%s</a><br>\n",goback,file->inc_in.s[i],html(file->inc_in.s[i]));
  243.     fprintf(of,"</menu></dl>\n");
  244.    }
  245.  
  246.  if(file->f_refs.n || file->v_refs.n)
  247.     fprintf(of,"<dl compact>\n");
  248.  
  249.  if(file->f_refs.n)
  250.    {
  251.     int others=0;
  252.     fprintf(of,"<dt>References Functions:\n<dd><menu>\n");
  253.     for(i=0;i<file->f_refs.n;i++)
  254.       {
  255.        char *temp=strchr(file->f_refs.s[i],':'),*filen;
  256.        if(temp)
  257.          {
  258.           temp[-1]=0;
  259.           filen=&temp[2];
  260.           fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#func_%s\">%s()  :  %s</a>\n",goback,filen,file->f_refs.s[i],html(file->f_refs.s[i]),html(filen));
  261.           temp[-1]=' ';
  262.          }
  263.        else
  264.           others++;
  265.       }
  266.  
  267.     if(others)
  268.       {
  269.        fprintf(of,"<li>");
  270.        for(i=0;i<file->f_refs.n;i++)
  271.           if(!strchr(file->f_refs.s[i],':'))
  272.              fprintf(of,--others?" %s(),":" %s()",html(file->f_refs.s[i]));
  273.        fprintf(of,"\n");
  274.       }
  275.     fprintf(of,"</menu>\n");
  276.    }
  277.  
  278.  if(file->v_refs.n)
  279.    {
  280.     int others=0;
  281.     fprintf(of,"<dt>References Variables:\n<dd><menu>\n");
  282.     for(i=0;i<file->v_refs.n;i++)
  283.       {
  284.        char *temp=strchr(file->v_refs.s[i],':'),*filen;
  285.        if(temp)
  286.          {
  287.           temp[-1]=0;
  288.           filen=&temp[2];
  289.           fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#var_%s\">%s  :  %s</a>\n",goback,filen,file->v_refs.s[i],html(file->v_refs.s[i]),html(filen));
  290.           temp[-1]=' ';
  291.          }
  292.        else
  293.           others++;
  294.       }
  295.  
  296.     if(others)
  297.       {
  298.        fprintf(of,"<li>");
  299.        for(i=0;i<file->v_refs.n;i++)
  300.           if(!strchr(file->v_refs.s[i],':'))
  301.              fprintf(of,--others?" %s,":" %s",html(file->v_refs.s[i]));
  302.        fprintf(of,"\n");
  303.       }
  304.     fprintf(of,"</menu>\n");
  305.    }
  306.  
  307.  if(file->f_refs.n || file->v_refs.n)
  308.     fprintf(of,"</dl>\n");
  309. }
  310.  
  311.  
  312. /*++++++++++++++++++++++++++++++++++++++
  313.   Write an Include structure out.
  314.  
  315.   Include inc The Include structure to output.
  316.   ++++++++++++++++++++++++++++++++++++++*/
  317.  
  318. static void WriteHTMLInclude(Include inc)
  319. {
  320.  if(inc->comment)
  321.     fprintf(of,"%s\n<p>\n",html(inc->comment));
  322.  
  323.  fprintf(of,"<menu>\n");
  324.  
  325.  if(inc->scope==LOCAL)
  326.     fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#file\"><tt>#include "%s"</tt></a>\n",goback,inc->name,html(inc->name));
  327.  else
  328.     fprintf(of,"<li><tt>#include <%s></tt>\n",html(inc->name));
  329.  
  330.  if(inc->includes)
  331.     WriteHTMLSubInclude(inc->includes,1);
  332.  
  333.  fprintf(of,"</menu>\n");
  334. }
  335.  
  336.  
  337. /*++++++++++++++++++++++++++++++++++++++
  338.   Write an Sub Include structure out. (An include structure that is included from another file.)
  339.  
  340.   Include inc The Include structure to output.
  341.  
  342.   int depth The depth of the include hierarchy.
  343.   ++++++++++++++++++++++++++++++++++++++*/
  344.  
  345. static void WriteHTMLSubInclude(Include inc,int depth)
  346. {
  347.  fprintf(of,"<menu>\n");
  348.  
  349.  while(inc)
  350.    {
  351.     if(inc->scope==LOCAL)
  352.        fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#file\"><tt>#include "%s"</tt></a>\n",goback,inc->name,html(inc->name));
  353.     else
  354.        fprintf(of,"<li><tt>#include <%s></tt>\n",html(inc->name));
  355.  
  356.     if(inc->includes)
  357.        WriteHTMLSubInclude(inc->includes,depth+1);
  358.  
  359.     inc=inc->next;
  360.    }
  361.  
  362.  fprintf(of,"</menu>\n");
  363. }
  364.  
  365.  
  366. /*++++++++++++++++++++++++++++++++++++++
  367.   Write a Define structure out.
  368.  
  369.   Define def The Define structure to output.
  370.   ++++++++++++++++++++++++++++++++++++++*/
  371.  
  372. static void WriteHTMLDefine(Define def)
  373. {
  374.  int i;
  375.  int pargs=0;
  376.  
  377.  if(def->comment)
  378.     fprintf(of,"%s\n<p>\n",html(def->comment));
  379.  
  380.  fprintf(of,"<tt>#define %s",html(def->name));
  381.  
  382.  if(def->value)
  383.     fprintf(of," %s",html(def->value));
  384.  
  385.  if(def->args.n)
  386.    {
  387.     fprintf(of,"( ");
  388.     for(i=0;i<def->args.n;i++)
  389.        fprintf(of,i?", %s":"%s",html(def->args.s1[i]));
  390.     fprintf(of," )");
  391.    }
  392.  fprintf(of,"</tt><br>\n");
  393.  
  394.  for(i=0;i<def->args.n;i++)
  395.     if(def->args.s2[i])
  396.        pargs=1;
  397.  
  398.  if(pargs)
  399.    {
  400.     fprintf(of,"<dl compact>\n");
  401.     for(i=0;i<def->args.n;i++)
  402.        fprintf(of,"<dt><tt>%s</tt>\n<dd>%s\n",html(def->args.s1[i]),def->args.s2[i]?html(def->args.s2[i]):"");
  403.     fprintf(of,"</dl>\n");
  404.    }
  405. }
  406.  
  407.  
  408. /*++++++++++++++++++++++++++++++++++++++
  409.   Write a Typedef structure out.
  410.  
  411.   Typedef type The Typedef structure to output.
  412.   ++++++++++++++++++++++++++++++++++++++*/
  413.  
  414. static void WriteHTMLTypedef(Typedef type)
  415. {
  416.  if(!strncmp("enum",type->name,4))
  417.     fprintf(of,"\n<a name=\"type_enum_%s\">\n",&type->name[5]);
  418.  else
  419.     if(!strncmp("union",type->name,5))
  420.        fprintf(of,"\n<a name=\"type_union_%s\">\n",&type->name[6]);
  421.     else
  422.        if(!strncmp("struct",type->name,6))
  423.           fprintf(of,"\n<a name=\"type_struct_%s\">\n",&type->name[7]);
  424.        else
  425.           fprintf(of,"\n<a name=\"type_%s\">\n",type->name);
  426.  
  427.  if(type->type)
  428.     fprintf(of,"<hr>\n<h2>Typedef %s</h2>\n</a>\n",html(type->name));
  429.  else
  430.     fprintf(of,"<hr>\n<h2>Type %s</h2>\n</a>\n",html(type->name));
  431.  
  432.  if(type->comment)
  433.     fprintf(of,"%s\n<p>\n",html(type->comment));
  434.  
  435.  if(type->type)
  436.     fprintf(of,"<tt>typedef %s</tt><br>\n",html(type->type));
  437.  
  438.  if(type->sutype)
  439.    {
  440.     fprintf(of,"<menu>\n");
  441.     WriteHTMLStructUnion(type->sutype,0);
  442.     fprintf(of,"</menu>\n");
  443.    }
  444.  else
  445.     if(type->typexref)
  446.       {
  447.        fprintf(of,"<dl compact>\n<dt>See:\n<dd><menu>\n");
  448.        if(type->typexref->type)
  449.           fprintf(of,"<li><a href=\"#type_%s\">Typedef %s</a>\n",type->typexref->name,html(type->typexref->name));
  450.        else
  451.           if(!strncmp("enum",type->typexref->name,4))
  452.              fprintf(of,"<li><a href=\"#type_enum_%s\">Type %s</a>\n",&type->typexref->name[5],html(type->typexref->name));
  453.           else
  454.              if(!strncmp("union",type->typexref->name,5))
  455.                 fprintf(of,"<li><a href=\"#type_union_%s\">Type %s</a>\n",&type->typexref->name[6],html(type->typexref->name));
  456.              else
  457.                 if(!strncmp("struct",type->typexref->name,6))
  458.                    fprintf(of,"<li><a href=\"#type_struct_%s\">Type %s</a>\n",&type->typexref->name[7],html(type->typexref->name));
  459.        fprintf(of,"</menu></dl>\n");
  460.       }
  461. }
  462.  
  463.  
  464. /*++++++++++++++++++++++++++++++++++++++
  465.   Write a structure / union structure out.
  466.  
  467.   StructUnion su The structure / union to write.
  468.  
  469.   int depth The current depth within the structure.
  470.   ++++++++++++++++++++++++++++++++++++++*/
  471.  
  472. static void WriteHTMLStructUnion(StructUnion su, int depth)
  473. {
  474.  int i;
  475.  char* splitsu=NULL;
  476.  
  477.  splitsu=strstr(su->name,"{...}");
  478.  if(splitsu) splitsu[-1]=0;
  479.  
  480.  if(depth && su->comment)
  481.     fprintf(of,"<tt>%s      </tt>%s<br>\n",html(su->name),html(su->comment));
  482.  else
  483.     fprintf(of,"<tt>%s</tt><br>\n",html(su->name));
  484.  
  485.  if(su->comps)
  486.    {
  487.     fprintf(of,"<menu>\n");
  488.  
  489.     fprintf(of,"<tt>{</tt><br>\n");
  490.  
  491.     for(i=0;i<su->n_comp;i++)
  492.        WriteHTMLStructUnion(su->comps[i],depth+1);
  493.  
  494.     fprintf(of,"<tt>}</tt><br>\n");
  495.  
  496.     fprintf(of,"</menu>\n");
  497.  
  498.     if(splitsu)
  499.        fprintf(of,"<tt>%s</tt><br>\n",html(&splitsu[6]));
  500.    }
  501.  
  502.  if(splitsu) splitsu[-1]=' ';
  503. }
  504.  
  505.  
  506. /*++++++++++++++++++++++++++++++++++++++
  507.   Write a Variable structure out.
  508.  
  509.   Variable var The Variable structure to output.
  510.   ++++++++++++++++++++++++++++++++++++++*/
  511.  
  512. static void WriteHTMLVariable(Variable var)
  513. {
  514.  int i;
  515.  
  516.  if(var->scope&GLOBAL)
  517.     fprintf(of,"<hr>\n<a name=\"var_%s\">\n<h2>Global Variable %s</h2>\n</a>\n",var->name,html(var->name));
  518.  else
  519.     fprintf(of,"<a name=\"var_%s\">\n<b>%s</b>\n</a><br>\n",var->name,html(var->name));
  520.  
  521.  if(var->comment)
  522.     fprintf(of,"%s\n<p>\n",html(var->comment));
  523.  
  524.  switch(var->scope)
  525.    {
  526.    case LOCAL:
  527.     fprintf(of,"<tt>static %s</tt><br>\n",html(var->type));
  528.     break;
  529.    case EXTERNAL:
  530.     fprintf(of,"<tt>extern %s</tt><br>\n",html(var->type));
  531.     break;
  532.    default:
  533.     fprintf(of,"<tt>%s</tt><br>\n",html(var->type));
  534.     break;
  535.    }
  536.  
  537.  if(var->scope&(GLOBAL|LOCAL))
  538.    {
  539.     if(var->visible.n || var->used.n)
  540.        fprintf(of,"<dl compact>\n");
  541.  
  542.     if(var->visible.n)
  543.       {
  544.        fprintf(of,"<dt>Visible in:\n<dd><menu>\n");
  545.        for(i=0;i<var->visible.n;i++)
  546.           fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#file\">%s</a>\n",goback,var->visible.s[i],html(var->visible.s[i]));
  547.        fprintf(of,"</menu>\n");
  548.       }
  549.  
  550.     if(var->used.n)
  551.       {
  552.        fprintf(of,"<dt>Used in:\n<dd><menu>\n");
  553.        for(i=0;i<var->used.n;i++)
  554.          {
  555.           if(var->used.s[i][0]=='$')
  556.              fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#file\">%s</a>\n",goback,&var->used.s[i][1],html(&var->used.s[i][1]));
  557.           else
  558.             {
  559.              char *temp=strchr(var->used.s[i],':'),*file;
  560.              temp[-1]=0;
  561.              file=&temp[2];
  562.              if(var->scope&LOCAL)
  563.                 fprintf(of,"<li><a href=\"#func_%s\">%s()</a>\n",var->used.s[i],html(var->used.s[i]));
  564.              else
  565.                 fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#func_%s\">%s()  :  %s</a>\n",goback,file,var->used.s[i],var->used.s[i],html(file));
  566.              temp[-1]=' ';
  567.             }
  568.          }
  569.        fprintf(of,"</menu>\n");
  570.       }
  571.  
  572.     if(var->visible.n || var->used.n)
  573.        fprintf(of,"</dl>\n");
  574.    }
  575.  else
  576.     if(var->scope&EXTERNAL && var->defined)
  577.       {
  578.        fprintf(of,"<dl compact>\n<dt>Defined in:\n<dd><menu>\n");
  579.        fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#var_%s\">%s</a>",goback,var->defined,html(var->name),var->defined);
  580.        fprintf(of,"</menu></dl>\n");
  581.       }
  582. }
  583.  
  584.  
  585. /*++++++++++++++++++++++++++++++++++++++
  586.   Write a Function structure out.
  587.  
  588.   Function func The Function structure to output.
  589.   ++++++++++++++++++++++++++++++++++++++*/
  590.  
  591. static void WriteHTMLFunction(Function func)
  592. {
  593.  int i,pret,pargs;
  594.  char* comment2=NULL,*type;
  595.  
  596.  if(func->scope&GLOBAL)
  597.     fprintf(of,"<hr>\n<a name=\"func_%s\">\n<h2>Global Function %s()</h2>\n</a>\n",func->name,html(func->name));
  598.  else
  599.     fprintf(of,"<hr>\n<a name=\"func_%s\">\n<h2>Local Function %s()</h2>\n</a>\n",func->name,html(func->name));
  600.  
  601.  if(func->comment)
  602.    {
  603.     comment2=strstr(func->comment,"\n\n");
  604.     if(comment2)
  605.        comment2[0]=0;
  606.     fprintf(of,"%s\n<p>\n",html(func->comment));
  607.    }
  608.  
  609.  fprintf(of,"<tt>");
  610.  switch(func->scope)
  611.    {
  612.    case LOCAL:           fprintf(of,"static "); break;
  613.    case LOCAL+INLINED:   fprintf(of,"static inline "); break;
  614.    case INLINED:         fprintf(of,"inline "); break;
  615.    default:              ;
  616.    }
  617.  
  618.  if((type=strstr(func->type,"()")))
  619.     type[0]=0;
  620.  fprintf(of,"%s ( ",html(func->type));
  621.  
  622.  for(i=0;i<func->args.n;i++)
  623.     fprintf(of,i?", %s":"%s",html(func->args.s1[i]));
  624.  
  625.  if(type)
  626.    {fprintf(of," %s</tt><br>\n",html(&type[1]));type[0]='(';}
  627.  else
  628.     fprintf(of," )</tt><br>\n");
  629.  
  630.  pret =strncmp("void ",func->type,5) && func->cret;
  631.  for(pargs=0,i=0;i<func->args.n;i++)
  632.     pargs = pargs || ( strcmp("void",func->args.s1[i]) && func->args.s2[i] );
  633.  
  634.  if(pret || pargs)
  635.    {
  636.     fprintf(of,"<dl compact>\n");
  637.     if(pret)
  638.        fprintf(of,"<dt><tt>%s</tt>\n<dd>%s\n",html(func->type),func->cret?html(func->cret):"");
  639.     if(pargs)
  640.        for(i=0;i<func->args.n;i++)
  641.           fprintf(of,"<dt><tt>%s</tt>\n<dd>%s\n",html(func->args.s1[i]),func->args.s2[i]?html(func->args.s2[i]):"");
  642.     fprintf(of,"</dl>\n");
  643.    }
  644.  
  645.  if(comment2)
  646.    {
  647.     fprintf(of,"%s\n<p>\n",html(&comment2[2]));
  648.     comment2[0]='\n';
  649.    }
  650.  
  651.  if(func->protofile || func->calls.n || func->called.n || func->used.n || func->f_refs.n || func->v_refs.n)
  652.     fprintf(of,"<dl compact>\n");
  653.  
  654.  if(func->protofile)
  655.    {
  656.     fprintf(of,"<dt>Prototyped in:\n<dd><menu>\n");
  657.     fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#file\">%s</a>\n",goback,func->protofile,html(func->protofile));
  658.     fprintf(of,"</menu>\n");
  659.    }
  660.  
  661.  if(func->calls.n)
  662.    {
  663.     int others=0;
  664.     fprintf(of,"<dt>Calls:\n<dd><menu>\n");
  665.     for(i=0;i<func->calls.n;i++)
  666.       {
  667.        char *temp=strchr(func->calls.s[i],':'),*file;
  668.        if(temp)
  669.          {
  670.           temp[-1]=0;
  671.           file=&temp[2];
  672.           fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#func_%s\">%s()  :  %s</a>\n",goback,file,func->calls.s[i],html(func->calls.s[i]),html(file));
  673.           temp[-1]=' ';
  674.          }
  675.        else
  676.           others++;
  677.       }
  678.  
  679.     if(others)
  680.       {
  681.        fprintf(of,"<li>");
  682.        for(i=0;i<func->calls.n;i++)
  683.           if(!strchr(func->calls.s[i],':'))
  684.              fprintf(of,--others?" %s(),":" %s()",html(func->calls.s[i]));
  685.        fprintf(of,"\n");
  686.       }
  687.     fprintf(of,"</menu>\n");
  688.    }
  689.  
  690.  if(func->called.n)
  691.    {
  692.     fprintf(of,"<dt>Called by:\n<dd><menu>\n");
  693.     for(i=0;i<func->called.n;i++)
  694.       {
  695.        char *temp=strchr(func->called.s[i],':'),*file;
  696.        temp[-1]=0;
  697.        file=&temp[2];
  698.        fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#func_%s\">%s()  :  %s</a>\n",goback,file,func->called.s[i],html(func->called.s[i]),html(file));
  699.        temp[-1]=' ';
  700.       }
  701.     fprintf(of,"</menu>\n");
  702.    }
  703.  
  704.  if(func->used.n)
  705.    {
  706.     fprintf(of,"<dt>Used in:\n<dd><menu>\n");
  707.     for(i=0;i<func->used.n;i++)
  708.       {
  709.        if(func->used.s[i][0]=='$')
  710.           fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#file\">%s</a>\n",goback,&func->used.s[i][1],html(&func->used.s[i][1]));
  711.        else
  712.          {
  713.           char *temp=strchr(func->used.s[i],':'),*file;
  714.           temp[-1]=0;
  715.           file=&temp[2];
  716.           fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#func_%s\">%s()  :  %s</a>\n",goback,file,func->used.s[i],html(func->used.s[i]),html(file));
  717.           temp[-1]=' ';
  718.          }
  719.       }
  720.     fprintf(of,"</menu>\n");
  721.    }
  722.  
  723.  if(func->f_refs.n)
  724.    {
  725.     int others=0;
  726.     fprintf(of,"<dt>References Functions:\n<dd><menu>\n");
  727.     for(i=0;i<func->f_refs.n;i++)
  728.       {
  729.        char *temp=strchr(func->f_refs.s[i],':'),*file;
  730.        if(temp)
  731.          {
  732.           temp[-1]=0;
  733.           file=&temp[2];
  734.           fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#func_%s\">%s()  :  %s</a>\n",goback,file,func->f_refs.s[i],html(func->f_refs.s[i]),html(file));
  735.           temp[-1]=' ';
  736.          }
  737.        else
  738.           others++;
  739.       }
  740.  
  741.     if(others)
  742.       {
  743.        fprintf(of,"<li>");
  744.        for(i=0;i<func->f_refs.n;i++)
  745.           if(!strchr(func->f_refs.s[i],':'))
  746.              fprintf(of,--others?" %s(),":" %s()",html(func->f_refs.s[i]));
  747.        fprintf(of,"\n");
  748.       }
  749.     fprintf(of,"</menu>\n");
  750.    }
  751.  
  752.  if(func->v_refs.n)
  753.    {
  754.     int others=0;
  755.     fprintf(of,"<dt>References Variables:\n<dd><menu>\n");
  756.     for(i=0;i<func->v_refs.n;i++)
  757.       {
  758.        char *temp=strchr(func->v_refs.s[i],':'),*file;
  759.        if(temp)
  760.          {
  761.           temp[-1]=0;
  762.           file=&temp[2];
  763.           fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#var_%s\">%s  :  %s</a>\n",goback,file,func->v_refs.s[i],html(func->v_refs.s[i]),html(file));
  764.           temp[-1]=' ';
  765.          }
  766.        else
  767.           others++;
  768.       }
  769.  
  770.     if(others)
  771.       {
  772.        fprintf(of,"<li>");
  773.        for(i=0;i<func->v_refs.n;i++)
  774.           if(!strchr(func->v_refs.s[i],':'))
  775.              fprintf(of,--others?" %s,":" %s",html(func->v_refs.s[i]));
  776.        fprintf(of,"\n");
  777.       }
  778.     fprintf(of,"</menu>\n");
  779.    }
  780.  
  781.  if(func->protofile || func->calls.n || func->called.n || func->used.n || func->f_refs.n || func->v_refs.n)
  782.     fprintf(of,"</dl>\n");
  783. }
  784.  
  785.  
  786. /*++++++++++++++++++++++++++++++++++++++
  787.   Write out a file that will include the current information.
  788.  
  789.   char* name The name of the file.
  790.   ++++++++++++++++++++++++++++++++++++++*/
  791.  
  792. static void WriteHTMLDocument(char* name)
  793. {
  794.  FILE *in,*out;
  795.  char line[256];
  796.  int seen=0;
  797.  char *inc_file,*ofile,*ifile;
  798.  
  799.  inc_file=ConcatStrings(6,"<a href=\"",goback,name,HTML_FILE"#file\">",name,"</a><br>\n");
  800.  ifile=ConcatStrings(4,option_odir,"/",option_name,HTML_FILE);
  801.  ofile=ConcatStrings(4,option_odir,"/",option_name,HTML_FILE_BACKUP);
  802.  
  803.  in =fopen(ifile,"r");
  804.  out=fopen(ofile,"w");
  805.  
  806.  if(!out)
  807.    {fprintf(stderr,"cxref: Failed to open the main HTML output file '%s'\n",ofile);exit(1);}
  808.  
  809.  if(!in)
  810.    {
  811.     WriteHTMLPreamble(out,ConcatStrings(3,"Cross reference of ",option_name,"."));
  812.     fprintf(out,"<h1>Source Files</h1>\n\n");
  813.    }
  814.  
  815.  if(in)
  816.     while(fgets(line,256,in))
  817.       {
  818.        if(!strcmp(inc_file,line))
  819.           seen=1;
  820.        if((!strcmp("<!-- Appendix -->\n",line) || !strcmp("<!-- End-Of-Doc -->\n",line)) && !seen)
  821.          {fputs(inc_file,out);fputs("\n",out);seen=1;}
  822.        fputs(line,out);
  823.       }
  824.  
  825.  if(!in)
  826.    {
  827.     fputs(inc_file,out);
  828.     WriteHTMLPostamble(out);
  829.    }
  830.  
  831.  if(in)
  832.    {
  833.     fclose(in);
  834.     unlink(ifile);
  835.    }
  836.  
  837.  fclose(out);
  838.  rename(ofile,ifile);
  839. }
  840.  
  841.  
  842. /*++++++++++++++++++++++++++++++++++++++
  843.   Write out a standard pre-amble.
  844.  
  845.   FILE* f The file to write the pre amble to.
  846.  
  847.   char* title The title of the file.
  848.   ++++++++++++++++++++++++++++++++++++++*/
  849.  
  850. static void WriteHTMLPreamble(FILE* f,char* title)
  851. {
  852.  fputs("<!-- This HTML file generated by cxref. -->\n",f);
  853.  fputs("<!-- cxref program (c) Andrew M. Bishop 1995. -->\n",f);
  854.  fputs("\n",f);
  855.  fputs("<HTML>\n",f);
  856.  fputs("\n",f);
  857.  fputs("<HEAD>\n",f);
  858.  fputs("<TITLE>\n",f);
  859.  fputs(title,f);fputs("\n",f);
  860.  fputs("</TITLE>\n",f);
  861.  fputs("</HEAD>\n",f);
  862.  fputs("\n",f);
  863.  fputs("<BODY>\n",f);
  864.  fputs("\n",f);
  865.  fputs("<!-- Begin-Of-Doc -->\n",f);
  866.  fputs("\n",f);
  867. }
  868.  
  869.  
  870. /*++++++++++++++++++++++++++++++++++++++
  871.   Write out a standard post-amble. This includes a table of contents and the end of document marker.
  872.  
  873.   FILE* f The file to write the post amble to.
  874.   ++++++++++++++++++++++++++++++++++++++*/
  875.  
  876. static void WriteHTMLPostamble(FILE* f)
  877. {
  878.  fputs("\n",f);
  879.  fputs("<!-- End-Of-Doc -->\n",f);
  880.  fputs("\n",f);
  881.  fputs("</BODY>\n",f);
  882.  fputs("</HTML>\n",f);
  883. }
  884.  
  885.  
  886. /*++++++++++++++++++++++++++++++++++++++
  887.   Write out the appendix information.
  888.  
  889.   StringList* files The list of files to write.
  890.  
  891.   StringList* funcs The list of functions to write.
  892.  
  893.   StringList* vars The list of variables to write.
  894.  
  895.   StringList* types The list of types to write.
  896.   ++++++++++++++++++++++++++++++++++++++*/
  897.  
  898. void WriteHTMLAppendix(StringList* files,StringList* funcs,StringList* vars,StringList* types)
  899. {
  900.  char* ofile;
  901.  int i;
  902.  
  903.  for(goback="",i=strlen(option_name);i>0;i--)
  904.     if(option_name[i]=='/')
  905.        goback=ConcatStrings(2,goback,"../");
  906.  
  907.  /* Write the bits to the including file. */
  908.  
  909.  AddHTMLAppendix();
  910.  
  911.  /* Open the file */
  912.  
  913.  ofile=ConcatStrings(4,option_odir,"/",option_name,HTML_APDX_FILE);
  914.  
  915.  of=fopen(ofile,"w");
  916.  
  917.  if(!of)
  918.    {fprintf(stderr,"cxref: Failed to open the HTML appendix file '%s'\n",ofile);exit(1);}
  919.  
  920.  /* Write the file structure out */
  921.  
  922.  WriteHTMLPreamble(of,ConcatStrings(3,"Cross reference index of ",option_name,"."));
  923.  
  924.  fprintf(of,"\n<h1>Cross References</h1>\n\n");
  925.  
  926.  /* Write out the appendix of files. */
  927.  
  928.  if(files->n)
  929.    {
  930.     fprintf(of,"<hr>\n<a name=\"files\">\n<h2>Files</h2>\n</a>\n");
  931.     fprintf(of,"<menu>\n");
  932.     for(i=0;i<files->n;i++)
  933.        fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#file\">%s</a>\n",goback,files->s[i],html(files->s[i]));
  934.     fprintf(of,"</menu>\n");
  935.    }
  936.  
  937.  /* Write out the appendix of functions. */
  938.  
  939.  if(funcs->n)
  940.    {
  941.     fprintf(of,"<hr>\n<a name=\"functions\">\n<h2>Global Functions</h2>\n</a>\n");
  942.     fprintf(of,"<menu>\n");
  943.     for(i=0;i<funcs->n;i++)
  944.       {
  945.        char *temp=strchr(funcs->s[i],':'),*file;
  946.        temp[-1]=0;
  947.        file=&temp[2];
  948.        fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#func_%s\">%s()  :  %s</a>\n",goback,file,funcs->s[i],html(funcs->s[i]),html(file));
  949.        temp[-1]=' ';
  950.       }
  951.     fprintf(of,"</menu>\n");
  952.    }
  953.  
  954.  /* Write out the appendix of variables. */
  955.  
  956.  if(vars->n)
  957.    {
  958.     fprintf(of,"<hr>\n<a name=\"variables\">\n<h2>Global Variables</h2>\n</a>\n");
  959.     fprintf(of,"<menu>\n");
  960.     for(i=0;i<vars->n;i++)
  961.       {
  962.        char *temp=strchr(vars->s[i],':'),*file;
  963.        temp[-1]=0;
  964.        file=&temp[2];
  965.        fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#var_%s\">%s  :  %s</a>\n",goback,file,vars->s[i],html(vars->s[i]),html(file));
  966.        temp[-1]=' ';
  967.       }
  968.     fprintf(of,"</menu>\n");
  969.    }
  970.  
  971.  /* Write out the appendix of types. */
  972.  
  973.  if(types->n)
  974.    {
  975.     fprintf(of,"<hr>\n<a name=\"types\">\n<h2>Defined Types</h2>\n</a>\n");
  976.     fprintf(of,"<menu>\n");
  977.     for(i=0;i<types->n;i++)
  978.       {
  979.        char *temp=strchr(types->s[i],':'),*file;
  980.        temp[-1]=0;
  981.        file=&temp[2];
  982.        if(!strncmp("enum",types->s[i],4))
  983.           fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#type_enum_%s\">%s  :  %s</a>\n",goback,file,&types->s[i][5],html(types->s[i]),html(file));
  984.        else
  985.           if(!strncmp("union",types->s[i],5))
  986.              fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#type_union_%s\">%s  :  %s</a>\n",goback,file,&types->s[i][6],html(types->s[i]),html(file));
  987.           else
  988.              if(!strncmp("struct",types->s[i],6))
  989.                 fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#type_struct_%s\">%s  :  %s</a>\n",goback,file,&types->s[i][7],html(types->s[i]),html(file));
  990.              else
  991.                 fprintf(of,"<li><a href=\"%s%s"HTML_FILE"#type_%s\">%s  :  %s</a>\n",goback,file,types->s[i],html(types->s[i]),html(file));
  992.        temp[-1]=' ';
  993.       }
  994.     fprintf(of,"</menu>\n");
  995.    }
  996.  
  997.  WriteHTMLPostamble(of);
  998.  
  999.  fclose(of);
  1000.  
  1001. /* Clear the memory in html() */
  1002.  
  1003.  html(NULL); html(NULL); html(NULL); html(NULL);
  1004. }
  1005.  
  1006.  
  1007. /*++++++++++++++++++++++++++++++++++++++
  1008.   Add the appendix commands to the output file.
  1009.   ++++++++++++++++++++++++++++++++++++++*/
  1010.  
  1011. static void AddHTMLAppendix(void)
  1012. {
  1013.  FILE *in,*out;
  1014.  char line[256];
  1015.  int seen=0;
  1016.  char *ofile,*ifile;
  1017.  
  1018.  ifile=ConcatStrings(4,option_odir,"/",option_name,HTML_FILE);
  1019.  ofile=ConcatStrings(4,option_odir,"/",option_name,HTML_FILE_BACKUP);
  1020.  
  1021.  in =fopen(ifile,"r");
  1022.  out=fopen(ofile,"w");
  1023.  
  1024.  if(!in || !out)
  1025.    {fprintf(stderr,"cxref: Failed to open the HTML main output file '%s'\n",ofile);exit(1);}
  1026.  
  1027.  while(fgets(line,256,in))
  1028.    {
  1029.     if(!strcmp("<!-- Appendix -->\n",line))
  1030.        seen=1;
  1031.     if(!strcmp("<!-- End-Of-Doc -->\n",line) && !seen)
  1032.       {
  1033.        fputs("<!-- Appendix -->\n",out);
  1034.        fprintf(out,"<hr>\n<h1>Appendix</h1>\n\n");
  1035.        fprintf(out,"<a href=\"%s%s"HTML_APDX_FILE"#files\">Files</a><br>\n",goback,option_name);
  1036.        fprintf(out,"<a href=\"%s%s"HTML_APDX_FILE"#functions\">Global Functions</a><br>\n",goback,option_name);
  1037.        fprintf(out,"<a href=\"%s%s"HTML_APDX_FILE"#variables\">Global Variables</a><br>\n",goback,option_name);
  1038.        fprintf(out,"<a href=\"%s%s"HTML_APDX_FILE"#types\">Defined Types</a><br>\n",goback,option_name);
  1039.        fputs("\n",out);
  1040.       }
  1041.     fputs(line,out);
  1042.    }
  1043.  
  1044.  fclose(in);
  1045.  if(!seen)
  1046.     unlink(ifile);
  1047.  
  1048.  fclose(out);
  1049.  if(!seen)
  1050.     rename(ofile,ifile);
  1051. }
  1052.  
  1053.  
  1054. /*++++++++++++++++++++++++++++++++++++++
  1055.   Make the input string safe to output as HTML ( not < > & " ).
  1056.  
  1057.   char* html Returns a safe HTML string.
  1058.  
  1059.   char* c A non-safe HTML string.
  1060.  
  1061.   The function can only be called four times in each fprintf() since it returns one of only four static strings.
  1062.   ++++++++++++++++++++++++++++++++++++++*/
  1063.  
  1064. static char* html(char* c)
  1065. {
  1066.  static char safe[4][256],*malloced[4]={NULL,NULL,NULL,NULL};
  1067.  static int which=0;
  1068.  int i=0,j=0,len=256-5;              /* 5 is the longest possible inserted amount */
  1069.  char* ret;
  1070.  
  1071.  which=(which+1)%4;
  1072.  ret=safe[which];
  1073.  
  1074.  if(malloced[which])
  1075.    {Free(malloced[which]);malloced[which]=NULL;}
  1076.  
  1077.  if(c)
  1078.     do{
  1079.        for(;j<len && c[i];i++)
  1080.           switch(c[i])
  1081.             {
  1082.             case '<':
  1083.              ret[j++]='&';
  1084.              ret[j++]='l';
  1085.              ret[j++]='t';
  1086.              ret[j++]=';';
  1087.              break;
  1088.             case '>':
  1089.              ret[j++]='&';
  1090.              ret[j++]='g';
  1091.              ret[j++]='t';
  1092.              ret[j++]=';';
  1093.              break;
  1094.             case '"':
  1095.              ret[j++]='&';
  1096.              ret[j++]='q';
  1097.              ret[j++]='u';
  1098.              ret[j++]='o';
  1099.              ret[j++]='t';
  1100.              ret[j++]=';';
  1101.              break;
  1102.             case '&':
  1103.              ret[j++]='&';
  1104.              ret[j++]='a';
  1105.              ret[j++]='m';
  1106.              ret[j++]='p';
  1107.              ret[j++]=';';
  1108.              break;
  1109.             case '\n':
  1110.              if(j && ret[j-1]=='\n')
  1111.                {
  1112.                 ret[j-1]='<';
  1113.                 ret[j++]='b';
  1114.                 ret[j++]='r';
  1115.                 ret[j++]='>';
  1116.                }
  1117.             default:
  1118.              ret[j++]=c[i];
  1119.             }
  1120.  
  1121.        if(c[i])                 /* Not finished */
  1122.          {
  1123.           unsigned int est_size=(110*strlen(c)*j)/(100*i); /* guess 10% larger than current estimate */
  1124.  
  1125.           if(malloced[which])
  1126.              malloced[which]=Realloc(malloced[which],est_size);
  1127.           else
  1128.             {malloced[which]=Malloc(est_size); strncpy(malloced[which],ret,(unsigned)j);}
  1129.           ret=malloced[which];
  1130.           len=est_size-4;
  1131.          }
  1132.        else
  1133.          {ret[j]=0; ret=NULL;}
  1134.       }
  1135.     while(ret);
  1136.  else
  1137.     safe[which][0]=0;
  1138.  
  1139.  return(malloced[which]?malloced[which]:safe[which]);
  1140. }
  1141.